본문으로 건너뛰기

useEffect 내부의 비동기 동작 관리

React를 사용할 때, 컴포넌트의 생명주기를 관리하기 위해 useEffect 훅을 자주 사용하게 됩니다. 특히 비동기 작업을 수행할 때, useEffect의 사용법을 제대로 이해하는 것이 중요합니다. 이번 글에서는 useEffect 내부에서 비동기 작업을 관리하는 방법을 구체적인 예제와 함께 알아보겠습니다.

useEffect와 비동기 작업

useEffect는 컴포넌트가 렌더링된 후에 실행되는 코드 블록을 정의합니다. 여기서 비동기 작업을 수행할 때는 async/await 구문을 사용할 수 있습니다. 다만, useEffect 함수 자체를 비동기로 만들 수는 없으므로, 내부에 비동기 함수를 선언하여 호출해야 합니다.

비동기 함수 사용 예제

아래는 useEffect 내에서 비동기 작업을 수행하는 기본적인 예제입니다. 여기서는 데이터를 API로부터 가져오는 작업을 예시로 들었습니다.

import React, { useState, useEffect } from 'react';

function DataFetchingComponent() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
// 비동기 함수를 선언합니다.
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
console.error('Error fetching data:', error);
setLoading(false);
}
};

// 비동기 함수를 호출합니다.
fetchData();
}, []); // 빈 배열을 전달하여 컴포넌트가 처음 마운트될 때만 실행되도록 합니다.

if (loading) {
return <div>Loading...</div>;
}

return (
<div>
<h1>Data</h1>
<pre>{JSON.stringify(data, null, 2)}</pre>
</div>
);
}

export default DataFetchingComponent;

위 예제에서는 useEffect 내부에서 fetchData라는 비동기 함수를 선언하고 호출하고 있습니다. fetch를 사용하여 데이터를 가져오고, 데이터를 state에 저장한 후 로딩 상태를 업데이트합니다.

주의할 점

비동기 작업을 useEffect에서 수행할 때 주의해야 할 몇 가지 사항이 있습니다.

메모리 누수 방지

컴포넌트가 언마운트되는 경우, 비동기 작업이 완료되지 않았더라도 이를 중단할 필요가 있습니다. 그렇지 않으면 메모리 누수(memory leak)가 발생할 수 있습니다. 이를 방지하기 위해 useEffect의 클린업 함수를 사용할 수 있습니다.

useEffect(() => {
let isMounted = true;

const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
if (isMounted) {
setData(result);
setLoading(false);
}
} catch (error) {
if (isMounted) {
console.error('Error fetching data:', error);
setLoading(false);
}
}
};

fetchData();

return () => {
isMounted = false;
};
}, []);

이 예제에서는 isMounted 변수를 사용하여 컴포넌트가 마운트된 상태인지 확인합니다. 클린업 함수에서 isMountedfalse로 설정하여 컴포넌트가 언마운트되면 비동기 작업이 더 이상 상태를 업데이트하지 않도록 합니다.

비동기 함수 호출 순서

비동기 작업이 완료되는 순서를 보장하기 위해 await 키워드를 사용합니다. 이를 통해 코드의 실행 흐름을 동기식으로 만들 수 있습니다. 하지만, 여러 비동기 작업을 병렬로 실행해야 할 경우에는 Promise.all을 사용하는 것이 좋습니다.

useEffect(() => {
const fetchData = async () => {
try {
const [response1, response2] = await Promise.all([
fetch('https://api.example.com/data1'),
fetch('https://api.example.com/data2')
]);

const result1 = await response1.json();
const result2 = await response2.json();

setData({ result1, result2 });
setLoading(false);
} catch (error) {
console.error('Error fetching data:', error);
setLoading(false);
}
};

fetchData();
}, []);

위 코드에서는 Promise.all을 사용하여 두 개의 비동기 작업을 병렬로 실행하고, 모든 작업이 완료된 후 결과를 처리합니다.

더 알아보기

  • 컴포넌트 생명주기: 컴포넌트의 생명주기를 이해하면 useEffect를 적절히 사용할 수 있습니다.
  • 비동기 프로그래밍: async/awaitPromise에 대한 깊은 이해는 비동기 작업을 효과적으로 관리하는 데 도움이 됩니다.
  • 메모리 누수 방지: 컴포넌트 언마운트 시 비동기 작업을 중단하는 방법에 대해 더 알아보세요.

내용 요약과 다음 주제

이번 글에서는 useEffect 내에서 비동기 작업을 관리하는 방법을 예제와 함께 설명했습니다. 비동기 작업 시 주의할 점과 메모리 누수를 방지하는 방법도 함께 다루었습니다. 다음 주제인 컴포넌트 소개와 좋은 컴포넌트 이름에서는 컴포넌트를 정의하고, 좋은 이름을 짓는 방법에 대해 알아보겠습니다.